/*
 *	$Id: dot.cpp 176 2010-06-24 20:57:06Z wabsie $
 */

#include "dot.hpp"


string dotAttrib::toStr() {
	using boost::str;
	using boost::format;

	string ret;
	map_ss::const_iterator it;
	map_ss::const_iterator begin = attributes.begin();
	map_ss::const_iterator end = attributes.end();
	map_ss::const_iterator last = end;

	if (!attributes.empty())
		--last;

	for (it = begin; it != end; ++it) {
		ret += str(format("%1% = %2%") % it->first % it->second);
		ret += (it != last) ? ", " : "";
	}
	return ret;
}

////////////////////////////////////////////////////////////////////////////////

dotNode::dotNode(dotable *n)
:	uid(::stringify(n->getDOTuid()))
{
//	this->Set("label", n->getDOTlabel());
//	this->Set("shape", "ellipse");
}

dotNode::dotNode(const string& special)
:	uid(special)
{/* Intet her */}

string dotNode::toString() {
	using boost::str;
	using boost::format;
	return str(format("%1%\t[%2%];") % uid % this->toStr());
}

////////////////////////////////////////////////////////////////////////////////

dotKant::dotKant(dotable *from, dotable *to)
:	uidFrom(::stringify(from->getDOTuid())),
	uidTo(::stringify(to->getDOTuid()))
{/* Intet her */}

string dotKant::toString() {
	using boost::str;
	using boost::format;
	return str(format("%1% -> %2%\t[%3%];") % uidFrom % uidTo % this->toStr());
}

////////////////////////////////////////////////////////////////////////////////

dot::dot()
:	node_defaults("node"),	// Defaults for noder er prefixed med "node"
	edge_defaults("edge")	// Defaults for kanter er prefixed med "edge"
{
	/**	Nedenstående anvender "Named Parameter Idiom", jvf.:
	 *	http://www.parashift.com/c++-faq-lite/ctors.html#faq-10.18 
	 */

	// Emulate the look of Mathematica graphs
	
	this->nodeDefault()
		.Set("color", "#ddaa66")
		.Set("style", "filled")
		.Set("shape", "box")
		.Set("fontname", "monospace")
		.Set("fontsize", 9)
		.Set("fillcolor", "#ffeecc")
		.Set("fontcolor", "#000000")
		.Set("width", 0.03)
		.Set("height", 0.03);
			
	this->kantDefault()
		.Set("color", "#999999")
		.Set("weight", "1")
		.Set("fontsize", 8)
		.Set("fontcolor", "#444444")
		.Set("fontname", "Verdana")
		.Set("arrowsize", "0.5")
		.Set("arrowhead", "vee");
}

dotNode& dot::addNode(dotable *n) {
	assert(n != NULL);

	dotNode ny(n);
	dotNoder.push_back(ny);
	return dotNoder.back();		// Returnér reference til (kopi af) tmp
}

dotKant& dot::addKant(dotable *from, dotable *to) {
	assert(from != NULL);
	assert(to != NULL);
	
	dotKant ny(from, to);
	dotKanter.push_back(ny);
	return dotKanter.back();
}

dotNode& dot::nodeDefault() {
	return this->node_defaults;
}

dotNode& dot::kantDefault() {
	return this->edge_defaults;
}

string dot::toString() {
	static const string pre =
		"digraph graphname {\n"			// Vi bruger kun orienterede grafer
		"\tlayout=dot;\n"
//		"\tsplines=polyline;\n"
		"\tranksep=0.2;\n"
		"\tnodesep=0.2;\n"
		"\tmargin=0.0;\n";

	static const string post = "}";
	string ret;

	ret = pre;
	ret += "\t" + node_defaults.toString() + "\n";
	ret += "\t" + edge_defaults.toString() + "\n";
	ret += "\n";
	for(int i = 0 ; i < this->dotNoder.size() ; i++) {
		ret += "\t" + dotNoder[i].toString() + "\n";
	}
	ret += "\n";
	for(int i = 0 ; i < this->dotKanter.size() ; i++) {
		ret += "\t" + dotKanter[i].toString() + "\n";
	}
	ret += post;
	return ret;
}

void dot::writeDOTfile(const char *fPath) {
	ofstream f;
	f.open(fPath);
	f << this->toString();	// Udskriv indhold af string til tekstfil
	f.close();
	return;
}
